/**
 * Note容器类
 * @namespace Note.Container
 * 
 * 构造函数
 * @constructor Container
 * @author JunEnstein 2017-05-18
 * @param  string divId 元素id
 */
Note.Container = function(divId, canvasClass, width, height, enableDraw = true){
	// 成员变量的初始化
	this.width = width;
	this.height = height;
	/**
	 * div元素对象即Container的父容器
	 * @type {HTMLElement}
	 */
	this._parent = document.getElementById(divId);
	/**
	 * 背景层对象
	 * @type {Note.Background}
	 */
	var background = this._createCanvas(canvasClass, "background", width, height);
	this._backgroundLayer = new Note.BackgroundLayer(background);
	/**
	 * 缓冲层对象
	 * @type {Note.CacheLayer}
	 */
	var cache = this._createCanvas(canvasClass, "cache", width, height);
	this._cacheLayer = new Note.CacheLayer(cache);
	/**
	 * 绘图层对象
	 * @type {Note.DrawLayer}
	 */
	var draw = this._createCanvas(canvasClass, "draw", width, height);
	this._drawLayer = new Note.DrawLayer(draw, this._cacheLayer);
	this._drawLayer.setEnable(enableDraw);
	/**
	 * 控件层对象
	 * @type {Note.WidgetLayer}
	 */
	this._widgetLayer = new Note.WidgetLayer(this._parent);

	/**
	 * 绘图HTML元素(为了辅助计算鼠标位置)
	 * @type {HTMLElement}
	 */
	this._element = draw;
	/**
	 * 操作类型(draw表示绘图, widget表示添加控件)
	 * @type {String}
	 */
	this._operator = "draw";
	/**
	 * 控件所需的数据
	 * @type {Object}
	 */
	this._widgetName = null;

	// 设置默认操作类型
	this.setOperator("draw", "curve");

	// 鼠标事件的初始化
	EventOnHandler(this._element, "mousedown", this, "_mouseDown");
	EventOnHandler(document, "mousemove", this, "_mouseMove");
	EventOnHandler(document, "mouseup",   this, "_mouseUp");
};

/**
 * 创建canvas对象
 * @method _createCanvas
 * @author JunEnstein 2017-05-19
 * @param  string className css类名
 * @param  string type canvas的类型(指为哪一层进行服务)
 * @return string 返回创建好的canvas对象
 */
Note.Container.prototype._createCanvas = function(className, type, width, height){
	if(type == 'draw') zIndex = 100;
	else if(type == 'cache') zIndex = 99;
	else zIndex = 98;
	var canvas = document.createElement("canvas");
	canvas.width = width;
	canvas.height= height;
	canvas.className = className;
	canvas.style.width = width + 'px';
	canvas.style.height = height + 'px';
	canvas.id = "note-canvas-"+type;
	
	this._parent.appendChild(canvas);
	return canvas;
};

/**
 * 设置绘制形状
 * @method draw
 * @author JunEnstein 2017-05-19
 * @param  {String} shape 绘制图形的形状
 */
Note.Container.prototype.setOperator = function(operator, type){
	this._operator = operator;
	if(this._operator == 'draw'){
		var shape = this._drawLayer.draw(type);
		if(shape == 'Line'||shape == 'Curve'){
			this._element.style.cursor = "url('/images/pen-lg.ico'),default";
		}
		else if(shape == 'Rectangle' || shape == 'Ellipse'){
			this._element.style.cursor = "crosshair";
		}
		else{
			this._element.style.cursor = "default";
		}
	}else{
		if(type == "label"){
			this._element.style.cursor = "crosshair";
		}
		this._widgetName = type;
	}
};

/**
 * 鼠标点击事件
 * @method _mouseDown
 * @author JunEnstein 2017-05-19
 * @param  MouseEvent event 鼠标事件对象
 */
Note.Container.prototype._mouseDown = function(event){
	var point = this.convertPoint(event);
	if(this._operator == "widget"){
		var data = {
			name: this._widgetName,
			position: point
		};
		var widget = new Note.WidgetFactory(data);
		this._widgetLayer.append(widget);
		return ;
	}
	this._drawLayer.start();
	this._drawLayer.append(point);
};

/**
 * 鼠标移动事件
 * @method _mouseMove
 * @author JunEnstein 2017-05-19
 * @param  MouseEvent event 鼠标事件对象
 */
Note.Container.prototype._mouseMove = function(event){
	var point = this.convertPoint(event);
	this._drawLayer.append(point);
	this._drawLayer.refresh();
};

/**
 * 鼠标松开事件
 * @method _mouseUp
 * @author JunEnstein 2017-05-19
 * @param  MouseEvent event 鼠标事件对象
 */
Note.Container.prototype._mouseUp = function(event){
	var point = this.convertPoint(event);
	this._drawLayer.append(point);
	this._drawLayer.refresh();
	this._drawLayer.end();
	var shape = this._drawLayer.save();
	if(shape == null) return ;
	this._cacheLayer.addShape(shape);
};

/**
 * 坐标转化函数
 * @method convertPoint
 * @author JunEnstein 2017-05-19
 * @param  MouseEvent evnet 鼠标事件对象
 * @return Point{x:int, y:int} 转换完成的坐标
 */
Note.Container.prototype.convertPoint = function(event){
	var rect = this._element.getBoundingClientRect();
	var point = {
		x: event.clientX - rect.left,
		y: event.clientY - rect.top
	};
	var shape = this._drawLayer._shape;
	// 当鼠标样式为画笔时,鼠标位置偏差修正
	if(shape == 'Curve' || this._drawLayer._shape == 'Line')
		point.y += 32;
	return point;
};

/**
 * 设置画笔样式
 * @method setPainterStyles
 * @author JunEnstein 2017-05-19
 * @param  {Object} styles 画笔样式
 */
Note.Container.prototype.setPainterStyles = function(styles){
	this._drawLayer.setPainterStyles(styles);
	this._cacheLayer.setPainterStyles(styles);
};

/**
 * 设置橡皮样式
 * @method setEraserStyle
 * @author JunEnstein 2017-05-19
 * @param  {Object} styles 橡皮样式
 */
Note.Container.prototype.setEraserStyle = function(styles){
	this._drawLayer.setEraserStyle(styles);
};

/**
 * 容器初始化化
 * @method initialize
 * @author JunEnstein 2017-05-19
 * @param  Image bgImgSrc 背景图片路径
 */
Note.Container.prototype.initialize = function(bgImgSrc){
	var self = this;
	var bgImg = new Image();
	bgImg.src = bgImgSrc;
	self._backgroundLayer.initialize(bgImg);
};

/**
 * 从data数据中恢复对象状态
 * @method load
 * @author JunEnstein 2017-05-19
 * @param {Object} data 对象数据
 */
Note.Container.prototype.load = function(data){
	this._widgetLayer.load(data.widget);
	// this._drawLayer.load(data.draw); 绘图层不需要恢复
	this._cacheLayer.load(data.cache);
	this._backgroundLayer.load(data.background);
};

/**
 * 保存Contianer对象
 * @method save
 * @author JunEnstein 2017-05-19
 * @return {Object} 对象数据
 */
Note.Container.prototype.save = function(){
	var data = {
		widget: this._widgetLayer.save(),
		// draw:   this._drawLayer.save(), 绘图层不需要保存
		cache:  this._cacheLayer.save(),
		background: this._backgroundLayer.save(),
		width: this.width,
		height: this.height
	};
	return data;
};

/**
 * 保存cache和background层结合以后的数据
 * @method savedownloadinfo
 * @author yeweiyang 2017-01-09
 * @param  image 缓冲层图片
 * @param  image 背景层图片
 * @return url 压缩后数据
 */
 Note.Container.prototype.savedownloadinfo = function(cacheImg, bgImg, callback){
	var self = this;
	cacheImg.onload = function(event){
		self._backgroundLayer.compress(cacheImg);
		callback(self._backgroundLayer.save());
		bgImg.onload = function(){
			self._backgroundLayer.initialize(bgImg);
		}
	};
};